﻿Public Class Matrix

    Private m_Adjacencies As Double(,)
    Private m_Temporary As Double(,)
    Private ReadOnly m_r As Double
    Private ReadOnly m_Display As Display
    Private ReadOnly m_Precision As Double
    Private ReadOnly m_IndexOf As New Dictionary(Of Point, Integer)()
    Private ReadOnly m_Field As Double(,)

    Public Sub New(ByVal vertices As IList(Of Point), ByVal edges As IList(Of Pair(Of Point, Point)), ByVal r As Double, ByVal precision As Double, ByVal display As Display)
        ReDim m_Adjacencies(vertices.Count - 1, vertices.Count - 1)
        ReDim m_Temporary(vertices.Count - 1, vertices.Count - 1)

        m_r = r
        m_Precision = precision
        m_Display = display

        'Dim neutral As Double
        'Dim row As Double

        For i = 0 To vertices.Count - 1
            m_IndexOf(vertices(i)) = i
        Next

        For Each e In edges
            m_Adjacencies(m_IndexOf(e.First), m_IndexOf(e.Second)) = Math.Max(600 - Distance(e), 0)
            m_Adjacencies(m_IndexOf(e.Second), m_IndexOf(e.First)) = Math.Max(600 - Distance(e), 0)
        Next

        For i = 0 To vertices.Count - 1
            m_Adjacencies(i, i) = 650
        Next

        'make stochastic
        For i = 0 To vertices.Count - 1
            Dim sum As Double
            For j = 0 To vertices.Count - 1
                sum += m_Adjacencies(i, j)
            Next
            For j = 0 To vertices.Count - 1
                m_Adjacencies(i, j) = m_Adjacencies(i, j) / sum
            Next
            sum = 0.0
        Next

        m_Display.m_Form2.Show()

    End Sub

    Public Sub Run()
        'While Difference()
        Expand()
        Inflate()
        m_Display.ReDraw(m_Adjacencies, m_IndexOf, Difference)
        Display()
        'End While
    End Sub

    Private Sub Display()
        Dim output As String = "Expanded:"
        output += vbCrLf
        For i = 0 To m_Adjacencies.GetLength(0) - 1
            For j = 0 To m_Adjacencies.GetLength(1) - 1
                'm_Display.m_Form2.TextBox1.AppendText(m_Adjacencies(i, j).ToString("0.000"))
                'm_Display.m_Form2.TextBox1.AppendText(" ")
                output += m_Adjacencies(i, j).ToString("0.000 ")
            Next
            'm_Display.m_Form2.TextBox1.AppendText(vbCrLf)
            output += vbCrLf
        Next
        output += "Inflated:" + vbCrLf
        For i = 0 To m_Temporary.GetLength(0) - 1
            For j = 0 To m_Temporary.GetLength(1) - 1
                'm_Display.m_Form2.TextBox1.AppendText(m_Adjacencies(i, j).ToString("0.000"))
                'm_Display.m_Form2.TextBox1.AppendText(" ")
                output += m_Temporary(i, j).ToString("0.000 ")
            Next
            'm_Display.m_Form2.TextBox1.AppendText(vbCrLf)
            output += vbCrLf
        Next
        m_Display.m_Form2.TextBox1.SuspendLayout()
        m_Display.m_Form2.SuspendLayout()
        'm_Display.m_Form2.TextBox1.Clear()
        m_Display.m_Form2.TextBox1.Text = output
        m_Display.m_Form2.TextBox1.ResumeLayout()
        m_Display.m_Form2.ResumeLayout()
    End Sub

    'Hadamard
    Private Sub Inflate()
        For i = 0 To m_Adjacencies.GetLength(0) - 1
            Dim sum As Double
            For j = 0 To m_Adjacencies.GetLength(1) - 1
                m_Adjacencies(i, j) = m_Adjacencies(i, j) ^ m_r
                sum += m_Adjacencies(i, j)
            Next
            For j = 0 To m_Adjacencies.GetLength(1) - 1
                m_Adjacencies(i, j) = m_Adjacencies(i, j) / sum
            Next
            sum = 0.0
        Next
    End Sub

    'MatrixProduct
    Private Sub Expand()
        For i = 0 To m_Adjacencies.GetLength(0) - 1
            For j = 0 To m_Adjacencies.GetLength(1) - 1
                Dim sum As Double
                For k = 0 To m_Adjacencies.GetLength(0) - 1
                    sum += m_Adjacencies(i, k) * m_Adjacencies(k, j)
                Next
                m_Temporary(i, j) = sum
                sum = 0.0
            Next
        Next

        'Copy the matrix
        For i = 0 To m_Adjacencies.GetLength(0) - 1
            For j = 0 To m_Adjacencies.GetLength(1) - 1
                m_Adjacencies(i, j) = m_Temporary(i, j)
            Next
        Next

    End Sub

    Private Function Difference() As Boolean

        For i = 0 To m_Adjacencies.GetLength(0) - 1
            For j = 0 To m_Adjacencies.GetLength(1) - 1
                If Math.Abs(m_Adjacencies(i, j) - m_Temporary(i, j)) > m_Precision Then
                    Return True
                End If
            Next
        Next
        Return False

    End Function
End Class
